package com.server.tools;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

public class Tools {

	public static void main(String[] args) throws IOException {
    	compress("HelloHello", "bjkqmxpvo1g8xl7j");
    	for(int i=1;i<=10;i++) {
    		long time = System.currentTimeMillis();
        	System.out.println(uncompress(compress("Hello World - " + i, "bjkqmxpvo1g8xl7j"),"bjkqmxpvo1g8xl7j"));
        	System.out.println((System.currentTimeMillis() - time) + "ms");
    	}
	}
	
	static String[] chars = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z",
			"1","2","3","4","5","6","7","8","9","0"};
	/**
	 * 
	 * 产生随机字符串，不长于32位
	 * @param int $length
	 * @return 产生的随机字符串
	 */
	public static String getNonceStr(int length) 
	{  
		String ret ="";
		for ( int i = 0; i < length; i++ )  {  
			ret += chars[(int) (Math.random() * chars.length)];
		} 
		return ret;
	}
	
	public static String getMd5(String str){
		try {
	        // 生成一个MD5加密计算摘要
	        MessageDigest md = MessageDigest.getInstance("MD5");
	        // 计算md5函数
	        md.update(str.getBytes());
	        // digest()最后确定返回md5 hash值，返回值为8为字符串。因为md5 hash值是16位的hex值，实际上就是8位的字符
	        // BigInteger函数则将8位的字符串转换成16位hex值，用字符串来表示；得到字符串形式的hash值
	        String md5 = (new BigInteger(1, md.digest())).toString(16);
	        if(md5.length() <= 31){
	        	md5 = "0"+md5;
	        }
	        return md5;
	    } catch (Exception e) {
	        e.printStackTrace();
	    }
		return "";
	}
	
	/**
     * Description 根据键值进行加密
     * @param data
     * @param key  加密键byte数组
     * @return
     * @throws Exception
     */
    private static byte[] encrypt(byte[] data, byte[] key) {
    	
    	try {
    		// 生成一个可信任的随机数源
            SecureRandom sr = new SecureRandom();
     
            // 从原始密钥数据创建DESKeySpec对象
            DESKeySpec dks = new DESKeySpec(key);
     
            // 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey securekey = keyFactory.generateSecret(dks);
     
            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance("DES");
     
            // 用密钥初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
     
            return cipher.doFinal(data);
    	}catch (Exception e) {
			e.printStackTrace();
		}
        return null;
    }

	
	// Gzip压缩
	public static byte[] compressGzip(byte[] data) throws IOException {
		byte[] tArray = null;
		
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		GZIPOutputStream gzip = new GZIPOutputStream(out);
		gzip.write(data);
		gzip.close();
		
		tArray = out.toByteArray();
		out.close();
		return tArray;
		//return out.toString("ISO-8859-1");
	}
	
	//字符串用Gzip压缩然后转base64
	public static String compress(String str, String key){
		if (str == null || str.length() == 0) {
			return str;
		}

		byte[] tArray = null;
		
		try{
			tArray = compressGzip(str.getBytes());
		} catch (Exception e) {
			
		}

		BASE64Encoder tBase64Encoder = new BASE64Encoder();
		try {
			tArray = encrypt(tArray, key.getBytes());
		} catch (Exception e) {
			return null;
		}
		return tBase64Encoder.encode(tArray);
		
	}
	
	 /**
     * Description 根据键值进行解密
     * @param data
     * @param key  加密键byte数组
     * @return
     * @throws Exception
     */
    private static byte[] decrypt(byte[] data, byte[] key){
    	try {
    		// 生成一个可信任的随机数源
            SecureRandom sr = new SecureRandom();
     
            // 从原始密钥数据创建DESKeySpec对象
            DESKeySpec dks = new DESKeySpec(key);
     
            // 创建一个密钥工厂，然后用它把DESKeySpec转换成SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            SecretKey securekey = keyFactory.generateSecret(dks);
     
            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance("DES");
     
            // 用密钥初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
     
            return cipher.doFinal(data);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return null;
    }

	
	// 解压缩   
	public static String uncompress(String str,String key) throws IOException {
		if (str == null || str.length() == 0) {
			return str;
		}
		
		BASE64Decoder decoder = new BASE64Decoder();
		byte[] bytes = decoder.decodeBuffer(str);
		if(bytes == null) {
			return null;
		}
		bytes = decrypt(bytes, key.getBytes());
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		ByteArrayInputStream in = new ByteArrayInputStream(bytes);
		GZIPInputStream gunzip = new GZIPInputStream(in);
		byte[] buffer = new byte[256];
		int n;
		while ((n = gunzip.read(buffer))>= 0) {
			out.write(buffer, 0, n);
		}
		
		return out.toString();
	}
}
